#pragma once

#include <iostream>
#include <vector>
#include <unistd.h>
#include <pthread.h>
#include "Sem.hpp"
#include "Mutex.hpp"

static int gcap = 5;

template <typename T>
class RingQueue
{
public:
    RingQueue(int cap = gcap)
        : _cap(cap), _rq(cap),
          _space_sem(_cap), _data_sem(0),
          _p_step(0), _c_step(0)
    {
    }

    void Push(const T &in)
    {
        // 买票
        _space_sem.P();
        {
            LockGuard lockgurad(&_p_mutex);
            // 排队
            // _p_mutex.Lock();
            // 生产
            _rq[_p_step++] = in;
            _p_step %= _cap;

            // _p_mutex.Unlock();
        }
        _data_sem.V();
    }

    void Pop(T *out)
    {
        _data_sem.P();
        {
            LockGuard lockguard(&_c_mutex);
            // _c_mutex.Lock();
            // 消费
            *out = _rq[_c_step++];
            _c_step %= _cap;

            // _c_mutex.Unlock();
        }
        _space_sem.V();
    }

    ~RingQueue()
    {
    }

private:
    std::vector<T> _rq;
    int _cap;
    Sem _space_sem;
    Sem _data_sem;

    int _p_step;
    int _c_step;

    // 锁
    Mutex _p_mutex;
    Mutex _c_mutex;
};